package linear;

import java.util.Iterator;

/**
 * 链表
 */
public class LinkList<T> implements Iterable<T> {

    public LinkList() {
        // 初始化链表
        this.head = new Node(null, null);
        this.N = 0;
    }


    /**
     * 结点
     */
    private class Node {
        T data;
        Node next;

        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }
    }

    /**
     * 链表头指针
     */
    private Node head;
    /**
     * 元素个数
     */
    private int N;

    /**
     * 清空列表
     */
    public void clear() {
        head.next = null;
        head.data = null;
        N = 0;
    }

    /**
     * 判断是否为空
     */
    public boolean isEmpty() {
        return N == 0;
    }

    /**
     * 获取链表长度
     */
    public int length() {
        return N;
    }

    /**
     * 获取一个元素
     */
    public T get(int i) {
        if (i < 0 || i >= N) {
            throw new RuntimeException("位置不合法!");
        }
        // 第一个元素
        Node result = head.next;

        for (int j = 0; j < i; j++) {
            result = result.next;
        }
        return result.data;
    }

    /**
     * 在链表的尾部插入一个元素
     */
    public void insert(T t) {
        Node n = head;
        // 搜索最后一个结点
        while (n.next != null) {
            n = n.next;
        }
        // 创建并连接结点
        n.next = new Node(t, null);
        N++;
    }


    /**
     * 在i的位置插入一个元素
     */
    public void insert(int i, T t) {
        if (i == 0 && N == 0) {
            this.insert(t);
            return;
        }
        if (i < 0 || i > N) {
            throw new RuntimeException("位置不合法!");
        }
        // 第一个元素
        Node pre = head.next;
        // 搜索到当前的上一个结点
        for (int j = 0; j < i - 1; j++) {
            pre = pre.next;
        }
        // 当前结点
        Node current = pre.next;
        // 新建结点 并连接当前结点
        // 连接新节点到pre
        pre.next = new Node(t, current);
        N++;
    }

    /**
     * 删除一个指定元素
     */
    public T remove(int i) {
        if (i < 0 || i >= N) {
            throw new RuntimeException("位置不合法!");
        }
        // 第一个元素
        Node pre = head.next;
        // 搜索到当前的上一个结点
        for (int j = 0; j < i - 1; j++) {
            pre = pre.next;
        }
        // 当前结点
        Node current = pre.next;
        pre.next = current.next;
        N--;
        return current.data;
    }

    /**
     * 放回指定元素索引
     */
    public int indexOf(T t) {
        Node n = head;
        for (int i = 0; n.next != null; i++) {
            n = n.next;
            if (n.data.equals(t)) {
                return i;
            }
        }
        return -1;
    }


    @Override
    public Iterator<T> iterator() {
        return new LIterator();
    }

    private class LIterator implements Iterator<T> {
        private Node n;

        LIterator() {
            n = head;
        }

        @Override
        public boolean hasNext() {
            return n.next != null;
        }

        @Override
        public T next() {
            n = n.next;
            return n.data;
        }
    }

    /**
     * 反转
     */
    public void reverse() {
        if (isEmpty()) {
            return;
        }
        reverse(head.next);

    }

    private Node reverse(Node current) {
        // 递归出口
        if (current.next == null) {
            head.next = current;
            return current;
        }

        Node pre = reverse(current.next);
        pre.next = current;
        current.next = null;
        return current;
    }


    public static void main(String[] args) {
        LinkList<String> list = new LinkList<>();

        list.insert(0, "张三");
        list.insert(1, "李四");
        list.insert(2, "王五");
        list.insert(3, "赵六");
//测试length方法
        for (String s : list) {
            System.out.println(s);
        }
        System.out.println(list.length());
        System.out.println("-------------------");
//测试get方法
        System.out.println(list.get(2));
        System.out.println("------------------------");
//测试remove方法
        String remove = list.remove(1);
        System.out.println(remove);
        System.out.println(list.length());
        System.out.println("----------------");
        ;
        for (String s : list) {
            System.out.println(s);
        }

        System.out.println("反转");
        list.reverse();
        for (String s : list) {
            System.out.println(s);
        }

    }
}
